package videorent;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 *
 * @author Rafael Barretta
 * @author Dayana de Ponte
 */
public class VideoRent {

    private static int codigoAsociado;

    /**
     * Este metodo transforma una cadena de caracteres, a una fecha
     * del calendario Gregoriano, dado un patron.
     * @param mesAno Cadena de Caracteres del archivo.
     * @param patron Patrón de conversion.
     * @return GregorianCalendar Calendario Transformado.
     * @exception ParseException Excepción cuando no se puede parsear una fecha.
     */
    public static GregorianCalendar transformarFecha(String mesAno, String patron)
            throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat(patron);
        Date d = sdf.parse(mesAno);
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(d);
        cal.add(GregorianCalendar.MONTH, 1);

        return cal;
    }

    /**
     * Este metodo transforma un arreglo de String en un ArrayList<String>
     * @param arreglo Es el arreglo a transformar.
     * @return ArrayList arreglo de String Transformado.
     */
    public static ArrayList<String> transformarArrayList(String[] arreglo) {
        int j = 0;
        ArrayList<String> ListArreglo = new ArrayList<String>();

        while (j < arreglo.length) {
            ListArreglo.add(j, arreglo[j].trim());
            //  System.out.println("\nAAAAA: " + ListArreglo.get(j));
            j++;
        }

        return ListArreglo;
    }

    /**
     * Este metodo transforma una cadena de caracteres, separados por coma
     * en una Dirección Fiscal.
     * @param direccion Es la direccion fiscal separada por comas.
     * @return DireccionFiscal Es el objto Direccion Fiscal
     * @exception Exception Lanza una excepcion cuando la direccion de un asociado no cumple con elformato.
     */
    public static DireccionFiscal transformarDirFiscal(String direccion) throws Exception {
        String aux[] = direccion.split("\\s*,\\s*");

        if (aux.length != 5) {
            throw new Exception("La direccion de uno o más asociados"
                    + " no cumplen con el formato.");
        }

        return new DireccionFiscal(aux[0], aux[1], aux[2], aux[3], aux[4]);

    }

    /**
     * Este metodo guarda una película en el inventario.
     * @param articulo Arreglo de caracteres que contiene todos los datos de una Pelicula.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @exception Exception Lanza una excepcion cuando faltan argumentos correspondientes a una Pelicula.
     */
    public static void guardarPelicula(String[] articulo, HashMap<String, Object> inventario) throws Exception {

        ArrayList<String> directores = new ArrayList<String>();
        ArrayList<String> escritores = new ArrayList<String>();
        ArrayList<String> actores = new ArrayList<String>();

        if (articulo.length < 9 || articulo.length > 10) {
            throw new Exception("Datos incompletos de articulo pelicula" + articulo[0] + " " + articulo.length);
        } else {

            directores = transformarArrayList(articulo[6].split("\\s*,s*"));
            escritores = transformarArrayList(articulo[7].split("\\s*,s*"));
            actores = transformarArrayList(articulo[8].split("\\s*,s*"));

            //No tengo la secuela
            if (articulo.length == 9) {
                inventario.put(articulo[0], new Pelicula(articulo[0], Integer.parseInt(articulo[1].trim()), articulo[2], Integer.parseInt(articulo[3].trim()), articulo[4], articulo[5], directores, escritores, actores, "", "existencia"));
            } else {
                inventario.put(articulo[0], new Pelicula(articulo[0], Integer.parseInt(articulo[1].trim()), articulo[2], Integer.parseInt(articulo[3].trim()), articulo[4], articulo[5], directores, escritores, actores, articulo[9], "existencia"));
            }
        }
    }

    /**
     * Este metodo guarda una serie en el inventario.
     * @param articulo Arreglo de caracteres que contiene todos los datos de una Serie.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @exception Exception Lanza una excepcion cuando faltan argumentos correspondientes a una Serie.
     */
    private static void guardarSerie(String[] articulo, HashMap<String, Object> inventario) throws Exception {
        ArrayList<String> creadores = new ArrayList<String>();
        ArrayList<String> actores = new ArrayList<String>();

        if (articulo.length != 8) {
            throw new Exception("Datos incompletos de articulo serie" + articulo[0] + " " + articulo.length);
        } else {
            creadores = transformarArrayList(articulo[5].split("\\s*,s*"));
            actores = transformarArrayList(articulo[6].split("\\s*,s*"));

            inventario.put(articulo[0], new TemporadaSerie(articulo[0], Integer.parseInt(articulo[1].trim()), articulo[2], Integer.parseInt(articulo[3].trim()), Integer.parseInt(articulo[4].trim()), creadores, actores, Integer.parseInt(articulo[7].trim()), "existencia"));
        }
    }

    /**
     * Este metodo guarda un Juego Recreativo en el inventario.
     * @param articulo Arreglo de caracteres que contiene todos los datos de un Juego Recreativo.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @exception Exception Lanza una excepcion cuando faltan argumentos correspondientes a un Juego Recreativo.
     */
    private static void guardarJuegoRecreativo(String[] articulo, HashMap<String, Object> inventario) throws Exception {

        if (articulo.length != 7) {
            throw new Exception("Datos incompletos de articulo juego recreativo" + articulo[0] + " " + articulo.length);
        } else {
            inventario.put(articulo[0], new JuegoRecreativo(articulo[0], Integer.parseInt(articulo[1].trim()), articulo[2], articulo[3], articulo[4], articulo[5], Integer.parseInt(articulo[6].trim()), "existencia"));
        }
    }

    /**
     * Este metodo guarda un Juego Educativo en el inventario.
     * @param articulo Arreglo de caracteres que contiene todos los datos de un Juego Educativo.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @exception Exception Lanza una excepcion cuando faltan argumentos correspondientes a un Juego Educativo.
     */
    private static void guardarJuegoEducativo(String[] articulo, HashMap<String, Object> inventario) throws Exception {

        if (articulo.length != 6) {
            throw new Exception("Datos incompletos de articulo juego educativo" + articulo[0] + " " + articulo.length);
        } else {
            inventario.put(articulo[0], new JuegoEducativo(articulo[0], Integer.parseInt(articulo[1].trim()), articulo[2], articulo[3], articulo[4], Integer.parseInt(articulo[5].trim()), "existencia"));
        }
    }

    /**
     * Este metodo se encarga de leer un archivo que contiene el inventario (artículos).
     * @param archivo direccion del archivo a cargar.
     * @return  inventario Es el inventario de artículos disponibles.
     * @exception Exception Lanza una excepcion cuando faltan argumentos correspondientes a un artículo.
     */
    public static HashMap<String, Object> cargarArticulos(String archivo) throws Exception {
        FileReader fr = new FileReader(archivo);
        BufferedReader br = new BufferedReader(fr);
        String linea = null;
        int cantArt = 0;
        String articulo[] = null;
        HashMap<String, Object> inventario = new HashMap<String, Object>();

        if ((linea = br.readLine()) != null) {
            //   System.out.println(linea);
            cantArt = Integer.parseInt(linea);

            while (cantArt != 0) {
                linea = br.readLine();
                articulo = linea.split("\\s*&\\s*");
                //  System.out.println(linea);

                // Para lineas del archivo que contienen algun caracter.
                if (!(linea.trim()).equals("")) {

                    switch (articulo[0].toLowerCase().trim().charAt(0)) {
                        case 'p':
                            guardarPelicula(articulo, inventario);
                            break;
                        case 'e':
                            guardarJuegoEducativo(articulo, inventario);
                            break;
                        case 'r':
                            guardarJuegoRecreativo(articulo, inventario);
                            break;
                        case 's':
                            guardarSerie(articulo, inventario);
                            break;
                        default:
                            throw new Exception("Formato: "+archivo+" inválido.");
                    }
                }
                cantArt--;
            }
        } else {
            throw new Exception("Archivo con formato incorrecto. "
                    + "Verifique el formato del archivo " + archivo + ".");
        }
        fr.close();

        return inventario;
    }

    /**
     * Este metodo se encarga de leer un archivo que contiene a los asociados.
     * @param asociadosFile direccion del archivo a cargar.
     * @return  asociados HashMap de los asociados cargados desde el archivo.
     * @exception Exception Lanza una excepcion cuando faltan argumentos correspondientes al asociado.
     */
    //Se parametriza el HashMap como <String, Object> para poder guardar Asociado y AsociadoPremium
    public static HashMap<String, Object> cargarAsociados(String asociadosFile) throws Exception {
        HashMap<String, Object> Asociados = new HashMap<String, Object>();
        FileReader fr = new FileReader(asociadosFile);
        BufferedReader br = new BufferedReader(fr);
        int cedula;
        int telefono;
        int cantAsoc = 0;
        String codigo;
        String estado;
        String nombre;
        String apellido;
        String linea = null;
        String aux[];
        String asociadoS[] = null;
        TarjetaCredito tC;
        DireccionFiscal dirFiscal;
        GregorianCalendar fechaVenc;

        if ((linea = br.readLine()) != null) {
            asociadoS = linea.split("\\s+");
            cantAsoc = Integer.parseInt(asociadoS[0].trim());
            codigoAsociado = Integer.parseInt(asociadoS[1].trim());

            // Mientras  no se han leido los asociados del archivo.
            while (cantAsoc != 0) {
                linea = br.readLine();
                // Para lineas del archivo que contienen algun caracter.
                if (!(linea.trim()).equals("")) {
                    // Se separan los argumentos
                    asociadoS = linea.split("\\s*&\\s*");
                    // Si la linea no tiene la cantidad de argumentos adecuados.
                    if (asociadoS.length != 11) {
                        throw new Exception("Archivo " + asociadosFile + "con Formato Incorrecto. Parametros de cliente incorrectos.");
                    }
                    codigo = asociadoS[0].trim();
                    estado = asociadoS[1].trim();
                    cedula = Integer.parseInt(asociadoS[2].trim());
                    nombre = asociadoS[3].trim();
                    apellido = asociadoS[4].trim();
                    telefono = Integer.parseInt(asociadoS[5].trim());
                    dirFiscal = transformarDirFiscal(asociadoS[6].trim());
                    fechaVenc = transformarFecha("01/" + asociadoS[10].trim(), "dd/MM/yyyy");

                    tC = new TarjetaCredito(asociadoS[7].trim(), asociadoS[8].trim(), asociadoS[9].trim(), fechaVenc);

                    if (asociadoS[0].toLowerCase().trim().charAt(0) == 'p') {
                        AsociadoPremium asociado = new AsociadoPremium(codigo, estado, dirFiscal, tC, new ArrayList<Object>(), cedula, nombre, apellido, telefono);
                        Asociados.put(codigo, asociado);
                    } else if (asociadoS[0].toLowerCase().trim().charAt(0) == 'b') {
                        Asociado asociado = new Asociado(codigo, estado, dirFiscal, tC, new ArrayList<Object>(), cedula, nombre, apellido, telefono);
                        Asociados.put(codigo, asociado);
                    } else {
                        throw new Exception("Codigo Incorrecto");
                    }
                    cantAsoc--;
                }
            }
        } else {
            throw new Exception("Archivo con formato incorrecto. "
                    + "Verifique el formato del archivo " + asociadosFile + ".");
        }
        fr.close();

        return Asociados;
    }

    /**
     * Este metodo se encarga de asociar a un cliente.
     * @param acciones Parametros de la asociacion.
     * @param asociados Informacion de los asociados.
     * @param fwEmp FileWriter de las acciones de los empleados.
     * @param fecha fecha del dia de la asociacion.
     * @exception Exception Lanza una excepcion cuando faltan parametros para la asociacion.
     */
    public static void asociar(String[] acciones, HashMap<String, Object> asociados, FileWriter fwEmp, GregorianCalendar fecha) throws Exception {

        if (acciones.length != 11) {
            throw new Exception("Archivo con formato invalido: parametros asociacion incompleto");
        }

        String aux[] = null;
        int cedula = Integer.parseInt(acciones[1].trim());
        String nombre = acciones[2].trim();
        String apellido = acciones[3].trim();
        int telefono = Integer.parseInt(acciones[4].trim());
        DireccionFiscal dirFiscal = transformarDirFiscal(acciones[5].trim());
        String numTarjeta = acciones[6].trim();
        String banco = acciones[7].trim();
        String codSeguridad = acciones[8].trim();
        GregorianCalendar fechaVencTC = transformarFecha("01/" + acciones[9].trim(), "dd/MM/yyyy");
        TarjetaCredito tc = new TarjetaCredito(numTarjeta, banco, codSeguridad, fechaVencTC);
        String membresia = acciones[10].trim();
        String status = "activo";
        Asociado asoc;
        AsociadoPremium asocPremium;
        boolean repetido = false;

        Iterator it = asociados.entrySet().iterator();

        while (it.hasNext()) {
            Map.Entry e = (Map.Entry) it.next();
            Asociado a = (Asociado) e.getValue();

            if (a.getCedula() == cedula) {
                // Si ya esta asociada la persona, se imprime error 5.
                fwEmp.append("i & " + a.getCodigo() + " & 5\n");
                repetido = true;
                break;
            }
        }

        //La persona se esta registrando por primera vez
        if (!repetido) {
            //Si la tarjeta dada esta proxima a vencer, se registra como suspendido
            if (tc.proximaVencer(fecha)) {
                status = "suspendido";
            }
            // ATENCION QUITAR
            //            System.out.println("AQUI: " + tc.proximaVencer(fecha) + ", Status: " + status);

            if (membresia.toLowerCase().equals("basica")) {

                asoc = new Asociado("B" + codigoAsociado, status, dirFiscal, tc, new ArrayList<Object>(), cedula, nombre, apellido, telefono);
                asociados.put("B" + codigoAsociado, asoc);
                fwEmp.append("r & B" + codigoAsociado + "\n");

            } else if (membresia.toLowerCase().equals("premium")) {
                asocPremium = new AsociadoPremium("P" + codigoAsociado, status, dirFiscal, tc, new ArrayList<Object>(), cedula, nombre, apellido, telefono);
                asociados.put("P" + codigoAsociado, asocPremium);
                fwEmp.append("r & P" + codigoAsociado + "\n");

            } else {
                throw new Exception("Membresia no valida: " + membresia);
            }
            codigoAsociado++;
        }
    }

    // ATENCION REVISAR CALCULOS DE MULTAS
    /** Este Metodo le indica al empleado que debe recoger un artículo.
     * Este lo recoge y queda reflejado en el archivo de salida.
     * Además el articulo se suma de nuevo al inventario
     */
    public static void recogerArticulo(String[] acciones, HashMap<String, Object> inventario, HashMap<String, Object> asociados, FileWriter fwEmp, FileWriter fwFact, GregorianCalendar fecha) throws Exception {
        Alquiler alq;
        Object o;
        Object oi;
        int cantidad = 0;
        int cantArt = 0;
        Articulo a;
        AsociadoPremium ap;
        ArrayList<Object> facturar = new ArrayList<Object>();
        ArrayList<Object> operaciones;
        Iterator itAlq;
        String codCli = acciones[1];
        String codArt = acciones[2];
        double multa = 0.0;

        if (acciones.length != 3) {
            throw new Exception("Archivo con formato invalido: Los Parametros Recoleccion de articulos no cumplen con el formato especificado");
        }

        // Si el asociado es premium se le puede recoger el articulo solicitado
        if (asociados.get(codCli) instanceof AsociadoPremium) {

            ap = (AsociadoPremium) asociados.get(codCli);
            // obtenemos la lista de las operaciones
            operaciones = ap.getOperaciones();

            // Si el articulo esta en los articulos a retirar.
            itAlq = operaciones.iterator();
            //Iteramos por los alquileres de ese asociado
            while (itAlq.hasNext()) {
                Object oAlq = itAlq.next();
                //Si es una instancia de alquiler
                if (oAlq instanceof Alquiler) {
                    //Obtengo una copia del alquiler
                    alq = (Alquiler) oAlq;
                    if (alq.contieneArticulo(codArt) && alq.getMontoEntregado() != 0.0) {
                        // dependiendo del tipo de Articulo
                        o = alq.getArticulo(codArt);
                        oi = inventario.get(codArt);
                        cantArt = alq.getCantArticulos(codArt);
                        if (o instanceof Pelicula) {
                            Pelicula p = (Pelicula) o;
                            // Si la fecha esta vencida cobro una multa
                            if (p.getFechaDevolucion().after(fecha)) { // fecha vencida
                                //se calcula pero se factura una multa
                                multa = Alquiler.MULTA_PELICULA * cantArt * p.diasTieneVencido(fecha);
                            }
                            // Se recoge la pelicula
                            alq.rmoverArticulo(p); // Se quita del alquiler Actual
                            // Se reemplaza la lista de operaciones para ese asociado
                            ap.setOperaciones(operaciones);
                            // Se guarda la pelicula en el inventario
                            Pelicula pi = (Pelicula) oi;
                            cantidad = cantArt + pi.getCantidad();
                            pi.setCantidad(cantidad);
                            inventario.put(codArt, pi);

                            for (int i = 0; i < cantArt; i++) {
                                //Se escribe en el archivo de las acciones de los mpleados
                                fwEmp.append("b & " + codCli + " & " + codArt + "\n");
                            }
                            // Si Hay Multa
                            if (multa > 0.0) {
                                // Se factura la multa en este caso pasamos un solo articulo para facturar
                                facturar.add(p);
                                generarFactura(ap, facturar, "Multa", fwFact, multa, inventario);
                                // Se agrega el cobro de la multa en las acciones del empleado
                                fwEmp.append("f & " + codCli + " & " + multa + "\n");
                            }
                        } else if (o instanceof TemporadaSerie) {
                            TemporadaSerie t = (TemporadaSerie) o;

                            // Si la fecha esta vencida cobro una multa
                            if (t.getFechaDevolucion().after(fecha)) { // fecha vencida
                                //se calcula pero se factura una multa
                                multa = Alquiler.MULTA_SERIE * cantArt * t.diasTieneVencido(fecha);
                            }
                            // Se recoge la pelicula
                            alq.rmoverArticulo(t); // Se quita del alquiler Actual
                            // Se reemplaza la lista de operaciones para ese asociado
                            ap.setOperaciones(operaciones);
                            // Se guarda la pelicula en el inventario
                            TemporadaSerie ti = (TemporadaSerie) oi;
                            cantidad = cantArt + ti.getCantidad();
                            ti.setCantidad(cantidad);
                            inventario.put(codArt, ti);

                            for (int i = 0; i < cantArt; i++) {
                                //Se escribe en el archivo de las acciones de los mpleados
                                fwEmp.append("b & " + codCli + " & " + codArt + "\n");
                            }
                            // Si Hay Multa
                            if (multa > 0.0) {
                                // Se factura la multa en este caso pasamos un asolo articulo para facturar
                                facturar.add(t);
                                generarFactura(ap, facturar, "Multa", fwFact, multa, inventario);
                                // Se agrega el cobro de la multa en las acciones del empleado
                                fwEmp.append("f & " + codCli + " & " + multa + "\n");
                            }
                        } else if (o instanceof JuegoEducativo) {
                            JuegoEducativo je = (JuegoEducativo) o;

                            // Si la fecha esta vencida cobro una multa
                            if (je.getFechaDevolucion().after(fecha)) { // fecha vencida
                                //se calcula pero se factura una multa
                                multa = Alquiler.MULTA_JUEGO_EDUCATIVO * cantArt * je.diasTieneVencido(fecha);
                            }
                            // Se recoge la pelicula
                            alq.rmoverArticulo(je); // Se quita del alquiler Actual
                            // Se reemplaza la lista de operaciones para ese asociado
                            ap.setOperaciones(operaciones);
                            // Se guarda la pelicula en el inventario
                            JuegoEducativo jei = (JuegoEducativo) oi;
                            cantidad = cantArt + jei.getCantidad();
                            jei.setCantidad(cantidad);
                            inventario.put(codArt, jei);

                            for (int i = 0; i < cantArt; i++) {
                                //Se escribe en el archivo de las acciones de los mpleados
                                fwEmp.append("b & " + codCli + " & " + codArt + "\n");
                            }
                            // Si Hay Multa
                            if (multa > 0.0) {
                                // Se factura la multa en este caso pasamos un asolo articulo para facturar
                                facturar.add(je);
                                generarFactura(ap, facturar, "Multa", fwFact, multa, inventario);
                                // Se agrega el cobro de la multa en las acciones del empleado
                                fwEmp.append("f & " + codCli + " & " + multa + "\n");
                            }
                        } else if (o instanceof JuegoRecreativo) {
                            JuegoRecreativo jr = (JuegoRecreativo) o;

                            // Si la fecha esta vencida cobro una multa
                            if (jr.getFechaDevolucion().after(fecha)) { // fecha vencida
                                //se calcula pero se factura una multa
                                multa = Alquiler.MULTA_JUEGO_RECREATIVO * cantArt * jr.diasTieneVencido(fecha);
                            }
                            // Se recoge la pelicula
                            alq.rmoverArticulo(jr); // Se quita del alquiler Actual
                            // Se reemplaza la lista de operaciones para ese asociado
                            ap.setOperaciones(operaciones);
                            // Se guarda la pelicula en el inventario
                            JuegoRecreativo jri = (JuegoRecreativo) oi;
                            cantidad = cantArt + jri.getCantidad();
                            jri.setCantidad(cantidad);
                            inventario.put(codArt, jri);

                            for (int i = 0; i < cantArt; i++) {
                                //Se escribe en el archivo de las acciones de los mpleados
                                fwEmp.append("b & " + codCli + " & " + codArt + "\n");
                            }
                            // Si Hay Multa
                            if (multa > 0.0) {
                                // Se factura la multa en este caso pasamos un asolo articulo para facturar
                                facturar.add(jr);
                                generarFactura(ap, facturar, "Multa", fwFact, multa, inventario);
                                // Se agrega el cobro de la multa en las acciones del empleado
                                fwEmp.append("f & " + codCli + " & " + multa + "\n");
                            }
                        }
                    }
                }
            }
        } else { // si no es AP Premium.
            // Imprimimos error
            fwEmp.append("i & " + acciones[1] + " & 2\n");
        }
    }

    /** Esta funcion se encarga de procesar las devoluciones
     */
    public static void devolverArticulo(String[] acciones, HashMap<String, Object> inventario, HashMap<String, Object> asociados, FileWriter fwEmp, FileWriter fwAc, GregorianCalendar fechaConsiderada) throws Exception {

        Iterator it = asociados.entrySet().iterator();
        Iterator<Object> itOb;
        ArrayList<Object> operaciones = null;
        ArrayList<Object> articulos = null;
        ArrayList<Multa> multas = null;
        AsociadoPremium ap = null;
        Asociado a = null;
        String codAsoc = acciones[1];
        String codArt = acciones[2];
        int diasVencidos = 0;
        double multa = 0.0;
        int i = 0;
        int j = 0;
        boolean b = false;
        Alquiler alq = null;
        // Para cada Asociado obtenemos su lista de operaciones
        while (it.hasNext()) {
            // Obtenemos al asociado
            Map.Entry e = (Map.Entry) it.next();

            if (e.getValue() instanceof AsociadoPremium) {
                // Obtenemos el asociado
                ap = (AsociadoPremium) e.getValue();
                // Para cada asociado obtenemos las operaciones
                operaciones = ap.getOperaciones();
                multas = ap.getMultas();
            } else {
                a = (Asociado) e.getValue();
                operaciones = a.getOperaciones();
                multas = a.getMultas();
            }


            // Para cada Alquiler
            while (j < operaciones.size() && !b) {
                Object op = operaciones.get(j);
                if (op instanceof Alquiler) {
                    alq = (Alquiler) op;
                    // Obtengo los articulos que debo devolver hoy
                    articulos = alq.getArticulos();
                    i = 0;

                    while (i < articulos.size() && !b) {
                        Object oArt = articulos.get(i);
                        // Removemos el articulo del inventario

                        if (oArt instanceof Pelicula) {
                            Pelicula p = (Pelicula) oArt;
                            if (p.getCodigo().equals(codArt)) {
                                b = true;
                                articulos.remove(i);
                                Pelicula pi = (Pelicula) inventario.get(codArt);
                                //Aumentamos la cantidad del inventario
                                pi.setCantidad(pi.getCantidad() + 1);
                                diasVencidos = p.diasTieneVencido(fechaConsiderada);
                                multa = diasVencidos * Alquiler.MULTA_PELICULA;
                                Multa m = new Multa(p, multa);
                                multas.add(m);
                                break;
                            }
                        } else if (oArt instanceof TemporadaSerie) {
                            TemporadaSerie t = (TemporadaSerie) oArt;
                            if (t.getCodigo().equals(codArt)) {
                                b = true;
                                articulos.remove(i);
                                TemporadaSerie ti = (TemporadaSerie) inventario.get(codArt);
                                //Aumentamos la cantidad del inventario
                                ti.setCantidad(ti.getCantidad() + 1);
                                diasVencidos = t.diasTieneVencido(fechaConsiderada);
                                multa = diasVencidos * Alquiler.MULTA_SERIE;
                                Multa m = new Multa(t, multa);
                                multas.add(m);
                                break;
                            }
                        } else if (oArt instanceof JuegoEducativo) {
                            JuegoEducativo je = (JuegoEducativo) oArt;
                            if (je.getCodigo().equals(codArt)) {
                                b = true;
                                articulos.remove(i);
                                JuegoEducativo jei = (JuegoEducativo) inventario.get(codArt);
                                //Aumentamos la cantidad del inventario
                                jei.setCantidad(jei.getCantidad() + 1);
                                diasVencidos = je.diasTieneVencido(fechaConsiderada);
                                multa = diasVencidos * Alquiler.MULTA_JUEGO_EDUCATIVO;
                                Multa m = new Multa(je, multa);
                                multas.add(m);
                                break;
                            }
                        } else if (oArt instanceof JuegoRecreativo) {
                            JuegoRecreativo jr = (JuegoRecreativo) oArt;
                            if (jr.getCodigo().equals(codArt)) {
                                b = true;
                                articulos.remove(i);
                                JuegoRecreativo jri = (JuegoRecreativo) inventario.get(codArt);
                                //Aumentamos la cantidad del inventario
                                jri.setCantidad(jri.getCantidad() + 1);
                                diasVencidos = jr.diasTieneVencido(fechaConsiderada);
                                multa = diasVencidos * Alquiler.MULTA_JUEGO_RECREATIVO;
                                Multa m = new Multa(jr, multa);
                                multas.add(m);
                                break;
                            }
                        }
                        i++;
                    }
                    if (articulos.size() > 0) {
                        alq.setArticulos(articulos);
                    } else {
                        operaciones.remove(j);
                    }
                }

                j++;
            }

            if (e.getValue() instanceof AsociadoPremium && b) {
                ap.setOperaciones(operaciones);
                ap.setMultas(multas);
            } else if (e.getValue() instanceof Asociado && b) {
                a.setOperaciones(operaciones);
                a.setMultas(multas);
            } else {
                // Operacion No valida
                fwEmp.append("i " + codAsoc + " 7\n");
            }
        }
    }

    /**
     * Este metodo libera los articulos llevados a caja (para su compra o alquiler), una vez que
     * el cliente abandona la tienda.
     * @param acciones   contiene los parametros que se necesita para llevar a cabo una accion de abandono.
     *                   Estos parametros son: codigo cliente.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @param asociados  consiste en un HashMap que contiene informacion de todos los Asociados registrados.
     * @param clientes   consiste en un HashMap que contiene informacion de todos los Clientes registrados.
     * @param fwEmp      file writer del archivo de las acciones de empleado.
     * @exception        Exception en error al numero de parametros pasados mediante el parametro acciones.
     */
    public static void abandonarTienda(String[] acciones, HashMap<String, Object> inventario, HashMap<String, Object> asociados, HashMap<String, Cliente> clientes, FileWriter fwEmp) throws Exception {

        if (acciones.length == 2) {
            String codCliente = acciones[1];
            int k = 0;
            String codArticulo;

            if (asociados.containsKey(codCliente)) {
                //Se trata de un asociado

                Asociado a = (Asociado) asociados.get(codCliente);

                //Verificamos si posee articulos para alquilar o comprar para luego poder liberarlos
                ArrayList<Object> artCompra = a.obtenerArticulosCompra();
                ArrayList<Object> artAlquiler = a.obtenerArticulosAlquiler();

                //Iteramos por la lista de compras y sumamos 1 a la cantidad de ese art. en inventario
                while (k < artCompra.size()) {
                    Articulo art = (Articulo) artCompra.get(k);
                    codArticulo = art.getCodigo();
                    Articulo artInv = (Articulo) inventario.get(codArticulo);
                    artInv.setCantidad(artInv.getCantidad() + 1);
                    k++;
                }

                k = 0;

                //Iteramos por la lista de alquileres y sumamos 1 a la cantidad de ese art. en inventario
                while (k < artAlquiler.size()) {

                    Articulo art = (Articulo) artAlquiler.get(k);
                    codArticulo = art.getCodigo();
                    Articulo artInv = (Articulo) inventario.get(codArticulo);
                    artInv.setCantidad(artInv.getCantidad() + 1);
                    k++;
                }

                //Liberamos los articulos de compra y alquiler, en la lista de operaciones del asociado
                a.eliminarArticulosCompra();
                a.eliminarArticulosAlquiler();
            } else if (clientes.containsKey(codCliente)) {
                //Se trata de un cliente
                k = 0;
                Cliente c = clientes.get(codCliente);

                //Verificamos si se tienen articulos para comprar
                ArrayList<Object> artComp = c.obtenerArticulosCompra();

                //Iteramos por la lista de compras y sumamos 1 a la cantidad de ese art. en inventario
                while (k < artComp.size()) {
                    Articulo art = (Articulo) artComp.get(k);
                    codArticulo = art.getCodigo();
                    Articulo artInv = (Articulo) inventario.get(codArticulo);
                    artInv.setCantidad(artInv.getCantidad() + 1);
                    k++;
                }
                //Liberamos los articulos de compra del cliente
                c.eliminarArticulosCompra();
            }
        } else {
            throw new Exception("Archivo con formato invalido: parametros de abandonar tienda incompleto");
        }
    }

    /**
     * Este metodo imprime en un archivo la accion de pagar un articulo, sea por alquiler, venta o multa.
     * @param acciones   contiene los parametros que se necesita para llevar a cabo una accion de pago.
     *                   Estos parametros son: codigo cliente y monto entregado.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @param asociados  consiste en un HashMap que contiene informacion de todos los Asociados registrados.
     * @param clientes   consiste en un HashMap que contiene informacion de todos los Clientes registrados.
     * @param fwEmp      file writer del archivo de las acciones de empleado.
     * @param fwFac      file writer del archivo de las facturas.
     * @exception        Exception en error al numero de parametros pasados mediante el parametro acciones.
     */
    public static void pagar(String[] acciones, HashMap<String, Object> inventario, HashMap<String, Object> asociados, HashMap<String, Cliente> clientes, FileWriter fwEmp, FileWriter fwFac) throws Exception {

//ATENCION falta considerar el caso que la persona devuelva un articulo con multa

        if (acciones.length == 3) {
            String codCliente = acciones[1].trim();
            double montoEntregado = Double.parseDouble(acciones[2].trim());
            double subtotal = 0;
            int i = 0;

            //Verifico si la persona es un asociado
            if (asociados.containsKey(codCliente)) {

                Asociado a = (Asociado) asociados.get(codCliente);

                //Verifico si la persona a pagar tiene articulos para su compra o alquiler
                if (a.getOperaciones().isEmpty()) {
                    //La persona no tiene articulos para compra o alquiler, imprimo error 7
                    fwEmp.append("i & " + codCliente + " & 7\n");
                } else {
                    //La persona tiene articulos para compra o alquiler
                    //Calculamos el monto a pagar por los articulos
                    subtotal = a.obtenerSubtotal();

                    if (subtotal > montoEntregado) {
                        //La persona pago de menos, imprimo error 3
                        fwEmp.append("i & " + codCliente + " & 3\n");
                    } else if (subtotal < montoEntregado) {
                        //La persona pago de mas, imprimo error 4
                        fwEmp.append("i & " + codCliente + " & 4\n");
                    }

                    //Obtenemos los articulos para comprar
                    ArrayList<Object> artCompra = a.obtenerArticulosCompra();

                    //Borramos los articulos de la compra, ya que van a ser facturados y no necesitamos
                    //referenciarlos despues
                    a.eliminarArticulosCompra();

                    //Obtenemos los articulos para multa
                    ArrayList<Multa> artMulta = a.getMultas();

                    //Obtenemos los articulos para alquiler
                    ArrayList<Object> articulosAlquilar = a.obtenerArticulosAlquiler();

                    //Seteamos los valores montoEntregado y total
                    a.setearAlquiler(subtotal, montoEntregado);


                    //Unimos los articulos tanto de compra como de alquiler para generar factura
                    ArrayList<Object> articulosTotales = new ArrayList<Object>(artCompra);
                    articulosTotales.addAll(articulosAlquilar);
                    articulosTotales.addAll(artMulta);

                    //Imprimimos la accion en el archivo de empleados
                    fwEmp.append("f & " + a.getCodigo() + " & " + subtotal + "\n");

                    generarFactura(a, articulosTotales, "Compra o alquiler de Artículos", fwFac, subtotal, inventario);

                }
            } else if (clientes.containsKey(codCliente)) {

                Cliente c = clientes.get(codCliente);

                //Verifico si la persona a pagar tiene articulos para su compra
                ArrayList<Object> artComp = c.obtenerArticulosCompra();

                if (artComp.isEmpty()) {
                    //La persona no tiene articulos para compra o alquiler, imprimo error 7
                    fwEmp.append("i & " + codCliente + " & 7\n");
                } else {
                    //La persona tiene articulos para compra o alquiler
                    //Calculamos el monto a pagar por los articulos
                    subtotal = c.obtenerSubtotal();

                    if (subtotal > montoEntregado) {
                        //La persona pago de menos, imprimo error 3
                        fwEmp.append("i & " + codCliente + " & 3\n");
                    } else if (subtotal < montoEntregado) {
                        //La persona pago de mas, imprimo error 4
                        fwEmp.append("i & " + codCliente + " & 4\n");
                    }

                    //Borramos los articulos de la compra, ya que van a ser facturados y no necesitamos
                    //referenciarlos despues
                    c.eliminarArticulosCompra();

                    System.out.print(codCliente + " TOtal pagar: " + subtotal + "\n");


                    //Imprimimos la accion en el archivo de empleados
                    fwEmp.append("f & " + c.getCedula() + " & " + subtotal + "\n");

                    generarFactura(c, artComp, "Compra o alquiler de Artículos", fwFac, subtotal, inventario);

                }


            } else {
                //La persona no es asociado ni cliente, arrojo error  0
                fwEmp.append("i & " + codCliente + " & 0\n");
            }

        } else {
            throw new Exception("Archivo con formato invalido: parametros de pago incompleto");
        }
    }

    /**
     * Este metodo imprime en un archivo la accion de llevar a caja un articulo para su alquiler.
     * @param acciones   contiene los parametros que se necesita para llevar a cabo una accion de llevar articulo a caja.
     *                   Estos parametros son: codigo cliente y codigo de articulo.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @param asociados  consiste en un HashMap que contiene informacion de todos los Asociados registrados.
     * @param fwEmp      file writer del archivo de las acciones de empleado.
     * @exception        Exception en error al numero de parametros pasados mediante el parametro acciones.
     */
    public static void llevarACajaAlquiler(String[] acciones, HashMap<String, Object> inventario, HashMap<String, Object> asociados, FileWriter fwEmp, GregorianCalendar fecha) throws Exception {

        GregorianCalendar fechaConsiderar = (GregorianCalendar) fecha.clone();

        if (acciones.length == 3) {
            String codCliente = acciones[1].trim();
            String codArticulo = acciones[2].trim();
            boolean superaCantAudiovisuales = false;
            boolean superaCantInteractivos = false;


            //Si el asociado no esta registrado, se imprime error 2
            //Solo los asociados pueden llevar articulos a caja para alquiler.
            if (!asociados.containsKey(codCliente)) {
                fwEmp.append("i & " + codCliente + " & 2\n");
            } else {
                //El asociado esta registrado

                //Si no poseo el articulo en inventario, imprimo error 1
                if (!inventario.containsKey(codArticulo)) {
                    fwEmp.append("i & " + codCliente + " & 1\n");
                } else {

                    Object ob = asociados.get(codCliente);

                    if (ob instanceof AsociadoPremium) {
                        //Verificamos que el asociado premium no tenga en la lista una cantidad de
                        //articulos para alquilar mayor a la posible
                        AsociadoPremium ap = (AsociadoPremium) ob;
                        superaCantAudiovisuales = ap.cantidadMaximaArticulosAudiovisuales();
                        superaCantInteractivos = ap.cantidadMaximaArticulosInteractivos();

                    } else if (ob instanceof Asociado) {
                        //Verificamos que el asociado no tenga en la lista una cantidad de
                        //articulos para alquilar mayor a la posible
                        Asociado a = (Asociado) ob;
                        superaCantAudiovisuales = a.cantidadMaximaArticulosAudiovisuales();
                        superaCantInteractivos = a.cantidadMaximaArticulosInteractivos();
                    }

                    Asociado a = (Asociado) asociados.get(codCliente);

                    //Obtenemos el articulo del inventario
                    Object arti = inventario.get(codArticulo);

                    if (arti instanceof Audiovisual) {

                        if (superaCantAudiovisuales) {
                            //se supero la cantidad de articulos audiovisuales, se imprime error 7
                            fwEmp.append("i & " + codCliente + " & 7\n");
                        } else {
                            Audiovisual artAudio = (Audiovisual) arti;

                            //Verificamos la cantidad de ese articulo en inventario
                            if (artAudio.getCantidad() != 0) {

                                //Determinamos el tipo de articulo para guardarlo en la lista
                                //de articulos a alquilar
                                Object art = inventario.get(codArticulo);

                                if (art instanceof Pelicula) {
                                    Pelicula p = (Pelicula) art;
                                    fechaConsiderar.add(GregorianCalendar.DATE, Alquiler.PRESTAMO_DIAS_PELICULA);

                                    //Inicializamos la fecha de devolucion del articulo
                                    p.setFechaDevolucion(fechaConsiderar);
                                    a.guardarArticuloAlquiler(p);

                                } else if (art instanceof TemporadaSerie) {
                                    TemporadaSerie p = (TemporadaSerie) art;
                                    fechaConsiderar.add(GregorianCalendar.DATE, Alquiler.PRESTAMO_DIAS_SERIE);

                                    //Inicializamos la fecha de devolucion del articulo
                                    p.setFechaDevolucion(fechaConsiderar);
                                    a.guardarArticuloAlquiler(p);
                                }
                                //Disminuimos la cantidad de ese articulo en inventario
                                artAudio.setCantidad(artAudio.getCantidad() - 1);
                            } else {
                                //Imprimimos que el articulo no esta en existencia
                                fwEmp.append("i & " + codCliente + " & 1\n");
                            }
                        }
                    } else if (arti instanceof Interactivo) {

                        if (superaCantInteractivos) {
                            //se supero la cantidad de articulos interactivos, se imprime error 7
                            fwEmp.append("i & " + codCliente + " & 7\n");
                        } else {
                            Interactivo artInterac = (Interactivo) arti;

                            //Verificamos la cantidad de ese articulo en inventario
                            if (artInterac.getCantidad() != 0) {

                                //Determinamos el tipo de articulo para guardarlo en la lista
                                //de articulos a alquilar
                                Object art = inventario.get(codArticulo);

                                if (art instanceof TemporadaSerie) {
                                    TemporadaSerie p = (TemporadaSerie) art;
                                    fechaConsiderar.add(GregorianCalendar.DATE, Alquiler.PRESTAMO_DIAS_SERIE);

                                    //Inicializamos la fecha de devolucion del articulo
                                    p.setFechaDevolucion(fechaConsiderar);
                                    a.guardarArticuloAlquiler(p);

                                } else if (art instanceof JuegoEducativo) {
                                    JuegoEducativo p = (JuegoEducativo) art;
                                    fechaConsiderar.add(GregorianCalendar.DATE, Alquiler.PRESTAMO_DIAS_JUEGO_EDUCATIVO);

                                    //Inicializamos la fecha de devolucion del articulo
                                    p.setFechaDevolucion(fechaConsiderar);
                                    a.guardarArticuloAlquiler(p);

                                } else if (art instanceof JuegoRecreativo) {
                                    JuegoRecreativo p = (JuegoRecreativo) art;
                                    fechaConsiderar.add(GregorianCalendar.DATE, Alquiler.PRESTAMO_DIAS_JUEGO_RECREATIVO);

                                    //Inicializamos la fecha de devolucion del articulo
                                    p.setFechaDevolucion(fechaConsiderar);
                                    a.guardarArticuloAlquiler(p);
                                }
                                //Disminuimos la cantidad de ese articulo en inventario
                                artInterac.setCantidad(artInterac.getCantidad() - 1);
                            } else {
                                //Imprimimos que el articulo no esta en existencia
                                fwEmp.append("i & " + codCliente + " & 1\n");
                            }
                        }
                    }
                }
            }
        } else {
            throw new Exception("Archivo con formato invalido: parametros llevar a caja un articulo para su alquiler incompleto");
        }
    }

    /**
     * Este metodo imprime en un archivo la accion de llevar a caja un articulo para su compra.
     * @param acciones   contiene los parametros que se necesita para llevar a cabo una accion de llevar articulo a caja.
     *                   Estos parametros son: codigo cliente y codigo de articulo.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @param asociados  consiste en un HashMap que contiene informacion de todos los Asociados registrados.
     * @param clientes   consiste en un HashMap que contiene informacion de todos los Clientes registrados.
     * @param fwEmp      file writer del archivo de las acciones de empleado.
     * @exception        Exception en error al numero de parametros pasados mediante el parametro acciones.
     */
    public static void llevarACajaCompra(String[] acciones, HashMap<String, Object> inventario, HashMap<String, Object> asociados, HashMap<String, Cliente> clientes, FileWriter fwEmp) throws Exception {
        String codCliente = acciones[1].trim();
        String codArticulo, nombre, telefono;
        ArrayList<Object> articulos = new ArrayList<Object>();

        //se trata de un asociado
        if (acciones.length == 3) {
            codArticulo = acciones[2].trim();

            //Si el asociado no esta registrado, se imprime error 0
            if (!asociados.containsKey(codCliente)) {
                fwEmp.append("i & " + codCliente + " & 0\n");
            } else {
                //El asociado esta registrado

                //Si no poseo el articulo en inventario, imprimo error 1
                if (!inventario.containsKey(codArticulo)) {
                    fwEmp.append("i & " + codCliente + " & 1\n");
                } else {
                    Asociado a = (Asociado) asociados.get(codCliente);

                    //Obtenemos el articulo del inventario
                    Articulo arti = (Articulo) inventario.get(codArticulo);

                    //Verificamos la cantidad de ese articulo en inventario
                    if (arti.getCantidad() != 0) {

                        //Si esta disponible, determinamos el tipo de articulo para guardarlo en la lista
                        //de articulos a comprar
                        Object art = inventario.get(codArticulo);

                        if (art instanceof Pelicula) {
                            Pelicula p = (Pelicula) art;
                            a.guardarArticuloCompra(p);

                        } else if (art instanceof TemporadaSerie) {
                            TemporadaSerie p = (TemporadaSerie) art;
                            a.guardarArticuloCompra(p);

                        } else if (art instanceof JuegoEducativo) {
                            JuegoEducativo p = (JuegoEducativo) art;
                            a.guardarArticuloCompra(p);

                        } else if (art instanceof JuegoRecreativo) {
                            JuegoRecreativo p = (JuegoRecreativo) art;
                            a.guardarArticuloCompra(p);
                        }

                        //Disminuimos la cantidad de ese articulo en inventario
                        arti.setCantidad(arti.getCantidad() - 1);

                    } else {
                        //Imprimimos que el articulo no esta en existencia
                        fwEmp.append("i & " + codCliente + " & 1\n");
                    }
                }
            }
            //Se trata de un cliente
        } else if (acciones.length == 5) {

            System.out.println("Soy cliente");
            nombre = acciones[2].trim();
            telefono = acciones[3].trim();
            codArticulo = acciones[4].trim();

            //SI no poseo el articulo en inventario, imprimo error 1
            if (!inventario.containsKey(codArticulo)) {
                fwEmp.append("i & " + codCliente + " & 1\n");
            }


            if (!clientes.containsKey(codCliente)) {
                //Si el cliente no esta registrado, se imprime error 0
                fwEmp.append("i & " + codCliente + " & 0\n");

                Articulo art = (Articulo) inventario.get(codArticulo);

                //Verificamos la cantidad de ese articulo en inventario
                if (art.getCantidad() != 0) {

                    //Si esta disponible, determinamos el tipo de articulo para guardarlo en la lista
                    //de articulos a comprar
                    Object obj = inventario.get(codArticulo);

                    if (obj instanceof Pelicula) {
                        Pelicula p = (Pelicula) art;
                        articulos.add(p);

                    } else if (obj instanceof TemporadaSerie) {
                        TemporadaSerie p = (TemporadaSerie) art;
                        articulos.add(p);

                    } else if (obj instanceof JuegoEducativo) {
                        JuegoEducativo p = (JuegoEducativo) art;
                        articulos.add(p);

                    } else if (obj instanceof JuegoRecreativo) {
                        JuegoRecreativo p = (JuegoRecreativo) art;
                        articulos.add(p);
                    }

                    //Disminuimos la cantidad de ese articulo en inventario
                    art.setCantidad(art.getCantidad() - 1);

                } else {
                    //Imprimimos que el articulo no esta en existencia
                    fwEmp.append("i & " + codCliente + " & 1\n");
                }

                //Generamos una nueva compra
                Compra compra = new Compra(articulos);

                //Guardamos temporalmente la informacion del cliente
                Cliente client = new Cliente(Integer.parseInt(codCliente), nombre, "", Integer.parseInt(telefono), compra);
                clientes.put(codCliente, client);

            } else {
                //El cliente esta registrado
                Cliente c = clientes.get(codCliente);

                //Obtenemos el articulo del inventario
                Articulo art = (Articulo) inventario.get(codArticulo);

                //Verificamos la cantidad de ese articulo en inventario
                if (art.getCantidad() != 0) {

                    //Si esta disponible, determinamos el tipo de articulo para guardarlo en la lista
                    //de articulos a comprar
                    Object obj = inventario.get(codArticulo);

                    if (obj instanceof Pelicula) {
                        Pelicula p = (Pelicula) art;
                        c.guardarArticuloCompra(p);

                    } else if (obj instanceof TemporadaSerie) {
                        TemporadaSerie p = (TemporadaSerie) art;
                        c.guardarArticuloCompra(p);

                    } else if (obj instanceof JuegoEducativo) {
                        JuegoEducativo p = (JuegoEducativo) art;
                        c.guardarArticuloCompra(p);

                    } else if (obj instanceof JuegoRecreativo) {
                        JuegoRecreativo p = (JuegoRecreativo) art;
                        c.guardarArticuloCompra(p);
                    }

                    //Disminuimos la cantidad de ese articulo en inventario
                    art.setCantidad(art.getCantidad() - 1);

                } else {
                    //Imprimimos que el articulo no esta en existencia
                    fwEmp.append("i & " + codCliente + " & 1\n");
                }
            }
        } else {
            throw new Exception("Archivo con formato invalido: parametros llevar a caja un articulo para su compra incompleto");
        }
    }

    /**
     * Este metodo actualiza los datos de la tarjeta de credito de un asociado, cambia el estatus de un asociado
     * (de ser necesario) e imprime las acciones en un archivo.
     * @param acciones   contiene los parametros que se necesita para llevar a cabo una accion de actualizacion de TC.
     *                   Estos parametros son: codigo cliente y datos de la tarjeta de credito.
     * @param asociados  consiste en un HashMap que contiene informacion de todos los Asociados registrados.
     * @param fwEmp      file writer del archivo de las acciones de empleado.
     * @param fecha      fecha del dia a considerar.
     * @exception        Exception en error al numero de parametros pasados mediante el parametro acciones.
     * @exception        IOException Si no se puede escribir en el archivo de acciones del empleado (fwEmp).
     */
    public static void actualizarTC(String[] acciones, HashMap<String, Object> asociados, FileWriter fwEmp, GregorianCalendar fecha) throws Exception {

        if (acciones.length != 6) {
            throw new Exception("Archivo con formato invalido: parametros actualizacion tarjeta de credito incompleto");
        }

        String codAsociado = acciones[1].trim();
        String numTarjeta = acciones[2].trim();
        String banco = acciones[3].trim();
        String codSeguridad = acciones[4].trim();
        GregorianCalendar fechaVencTC = transformarFecha("01/" + acciones[5].trim(), "dd/MM/yyyy");
        String status = "suspendido";

        if (!asociados.containsKey(codAsociado)) {
            //Si la persona bajo ese codigo no esta registrada, se imprime error 0
            fwEmp.append("i & " + codAsociado + "& 0\n");

        } else {
            Asociado a = (Asociado) asociados.get(codAsociado);
            a.actualizarTarjeta(numTarjeta, banco, codSeguridad, fechaVencTC);
            fwEmp.append("t & " + codAsociado + "\n");

            //Hay que tomar en cuenta que a pesar que se este actualizando los datos de una tarjeta
            //si esta no es valida, igual la persona permanece como suspendida.

            //si la tarjeta no esta proxima a vencerse, se coloca como activo
            if (!a.chequearValidezTarjeta(fecha)) {
                status = "activo";
            }

            fwEmp.append("c & " + codAsociado + " & " + status + "\n");
            a.setEstado(status);
            asociados.put(codAsociado, a);

//            System.out.println("***********************************");
//            Asociado a2 = (Asociado) asociados.get(codAsociado);
//            TarjetaCredito tc2 = a2.gettC();
//            System.out.println("Datos*: " + tc2.getBanco() + " " + tc2.getCodSeg() + " " + tc2.getFechaVenc().get(GregorianCalendar.DAY_OF_MONTH) + "-" + tc2.getFechaVenc().get(GregorianCalendar.MONTH) + "-" + tc2.getFechaVenc().get(GregorianCalendar.YEAR) + " " + tc2.getNumero());
//            System.out.println("Status: " + a.getEstado());
        }
    }

    /**
     * Este metodo se encarga de chequear a los asociados para ver si su tarjeta no esta proxima a vencer
     * si esta proxima a vencer se suspende al asociado.
     * @param asociados Información de los asociados.
     * @param fwEmp FileWriter de las acciones de los empleados.
     * @param fecha fecha del dia con el que se va a comparar la fecha de vencimiento.
     * @exception IOException Si no se puede escribir en el archivo de acciones del empleado (fwEmp).
     */
    public static void chequearTcStatus(HashMap<String, Object> asociados, FileWriter fwEmp, GregorianCalendar fecha) throws Exception {
        Iterator it = asociados.entrySet().iterator();

        while (it.hasNext()) {
            Map.Entry e = (Map.Entry) it.next();
            Asociado a = (Asociado) e.getValue();
            //    System.out.println("** Dia considerado: " + fecha.get(GregorianCalendar.DAY_OF_MONTH) + "-" + fecha.get(GregorianCalendar.MONTH) + "-" + fecha.get(GregorianCalendar.YEAR));
            //     System.out.println("AAAAAA: " + e.getKey() + " " + a.getCodigo() +" " + a.getEstado());


            if (a.chequearValidezTarjeta(fecha)) {
                // Si el asociado no esta suspendido
                if (a.getEstado().equals("activo")) {
                    fwEmp.append("c &" + a.getCodigo() + "& suspendido\n");
                    a.setEstado("suspendido");
                    asociados.put("" + e.getKey(), a);
                }
            }
        }
    }

    /**
     * Este metodo imprime una nueva factura en el archivo de facturas.
     * @param a Asociado o cliente registrado de la tienda.
     * @param articulos Lista de articulos de compra y/o alquiler.
     * @param concepto Concepto de la factura.
     * @param factura FileWriter del archivo de facturas.
     * @param montoPagar Monto total a pagar por los articulos seleccionados.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @exception IOException Si no se puede escribir en el archivo de acciones del empleado (fwEmp).
     * @see IOException
     */
    private static void generarFactura(Object a, ArrayList<Object> articulos, String concepto, FileWriter factura, double montoPagar, HashMap<String, Object> inventario) throws IOException {
        int i = 0;
        String codArt = "";
        String linea = "---------------------------- FACTURA VIDEORENT -----------------------------------\n";
        Persona per = (Persona) a;
        Asociado as = null;

        if (a instanceof Asociado) {
            as = (Asociado) a;
            linea += "CÓDIGO: " + as.getCodigo() + "\n";
        }
        linea += "CÉDULA: " + per.getCedula() + "\n";
        linea += "NOMBRE: " + per.getNombre() + " " + per.getApellido() + "\n";
        linea += "TELÉFONO: " + per.getTelefono() + "\n";

        if (a instanceof Asociado) {
            DireccionFiscal df = as.getDirFiscal();
            linea += "DIRECCION: " + df.getCalle() + ", " + df.getNumero() + ", "
                    + df.getSector() + ", " + df.getCiudad() + ", " + df.getEstado() + "\n";
            linea += "DATOS TARJETA: "
                    + "\n\tNUMERO: " + (as.gettC()).getNumero() + "\n\tBANCO: " + (as.gettC()).getBanco()
                    + "\n\tCÓDIGO SEGURIDAD: " + (as.gettC()).getCodSeg() + "\n";
        }

        linea += "CONCEPTO: " + concepto + "\n";
        linea += "DATOS DEL ARTICULO:\n";

        while (i < articulos.size()) {
            //Obtenemos el codigo del articulo
            codArt = ((Articulo) articulos.get(i)).getCodigo();
            Object o = inventario.get(codArt);

            if (o instanceof Pelicula) {
                Pelicula p = (Pelicula) inventario.get(codArt);
                //ATENCION: se hace substring para no imprimir la cantidad y replaceAlL para no imprimir fecha de dev.
                linea += "\nPELICULA: " + p.obtenerDatos().substring(4).replaceAll("\\s&\\s\\d+/\\d+/\\d\\d\\d\\d", "");

            } else if (o instanceof TemporadaSerie) {
                TemporadaSerie p = (TemporadaSerie) inventario.get(codArt);
                linea += "\nSERIE: " + p.obtenerDatos().substring(4).replaceAll("\\s&\\s\\d+/\\d+/\\d\\d\\d\\d", "");

            } else if (o instanceof JuegoEducativo) {
                JuegoEducativo p = (JuegoEducativo) inventario.get(codArt);
                linea += "\nJ. EDUCATIVO: " + p.obtenerDatos().substring(4).replaceAll("\\s&\\s\\d+/\\d+/\\d\\d\\d\\d", "");

            } else if (o instanceof JuegoRecreativo) {
                JuegoRecreativo p = (JuegoRecreativo) inventario.get(codArt);
                linea += "\nJ. RECREATIVO: " + p.obtenerDatos().substring(4).replaceAll("\\s&\\s\\d+/\\d+/\\d\\d\\d\\d", "");
            }
            i++;
        }

        linea += "\n\nMONTO A PAGAR: " + montoPagar + " Bsf.";

        factura.append(linea);
        factura.append("\n----------------------------------------------------------------------------------\n\n");
    }

    // ATENCION ESTA MALA REVISAR
    /**
     * Este metodo se encarga de chequear a los asociados para ver si Tienen alquileres perdidos.
     * @param asociados Información de los asociados.
     * @param fwEmp FileWriter de las acciones de los empleados.
     * @param factura FileWriter del archivo donde se va a facturar.
     * @param fecha fecha del dia con el que se va a comparar la fecha de vencimiento.
     * @exception IOException Si no se puede escribir en el archivo de acciones del empleado (fwEmp).
     */
    public static void chequearPrestamosPerdidos(HashMap<String, Object> asociados, FileWriter fwEmp, FileWriter factura, GregorianCalendar fecha, HashMap<String, Object> inventario) throws Exception {
        ArrayList<Object> operaciones;
        ArrayList<Object> articulos = null;
        ArrayList<Object> articulosPerdidos = null;
        Iterator it = asociados.entrySet().iterator();
        Iterator opIt;
        double deuda = 0.0;
        Object o, oAlq, oArt;
        Alquiler alq;
        Asociado a;
        AsociadoPremium ap;
        Iterator<Object> iterArt;

        // iteramos sobre los asociados del hashmap.
        while (it.hasNext()) {
            Map.Entry e = (Map.Entry) it.next();
            o = e.getValue();
            if (o instanceof AsociadoPremium) {
                ap = (AsociadoPremium) o;
                // Para cada asociado obtenemos las operaciones
                operaciones = ap.getOperaciones();

            } else {
                a = (Asociado) o;
                // Para cada asociado obtenemos las operaciones
                operaciones = a.getOperaciones();

            }

            // Obtengo las operaciones que sean alquiler
            opIt = operaciones.iterator();

            // El asociado puede tener mas de un alquiler con
            // Articulos con fecha de devolucion vencida.
            // iteramos sobre las operaciones
            while (opIt.hasNext()) {
                oAlq = opIt.next();
                // Para cada Alquiler
                if (oAlq instanceof Alquiler) {

                    alq = (Alquiler) oAlq;

                    // Obtenemos los articulos de ese alquiler
                    articulos = alq.getArticulos();
                    iterArt = articulos.iterator();
                    // paara cada articulo
                    while (iterArt.hasNext()) {
                        // Obtengo el alrticulo
                        oArt = iterArt.next();
                        if (o instanceof Pelicula) {
                            Pelicula p = (Pelicula) oArt;
                            // Si esta perdido lo agrego a la lista
                            if (p.estaPerdido(fecha)) {
                                articulosPerdidos.add(p);
                            }
                        } else if (o instanceof TemporadaSerie) {
                            TemporadaSerie t = (TemporadaSerie) oArt;
                            if (t.estaPerdido(fecha)) {
                                articulosPerdidos.add(t);
                            }
                        } else if (o instanceof JuegoEducativo) {
                            JuegoEducativo je = (JuegoEducativo) oArt;
                            System.out.println("Codigo " + je.getCodigo());
                            if (je.estaPerdido(fecha)) {
                                articulosPerdidos.add(je);
                            }
                        } else if (o instanceof JuegoRecreativo) {
                            JuegoRecreativo jr = (JuegoRecreativo) oArt;
                            System.out.println("Codigo " + jr.getCodigo());
                            if (jr.estaPerdido(fecha)) {
                                articulosPerdidos.add(jr);
                            }
                        }
                    }

                    ArrayList<Object> articulos2 = new ArrayList<Object>();

                    //Cobro y quito todos los articulos perdidos
                    iterArt = articulosPerdidos.iterator();

                    System.out.println("TAM: ------------------->" + articulosPerdidos.size());
                    while (iterArt.hasNext()) {
                        // Obtengo el articulo
                        oArt = iterArt.next();
                        /*if (o instanceof Pelicula) {
                        Pelicula p = (Pelicula) oArt;
                        // Si esta perdido lo agrego a la lista
                        if (p.estaPerdido(fecha)) {
                        deuda = deuda + Alquiler.PRECIO_PELICULA;
                        } else {
                        articulos2.add(p);
                        }
                        } else if (o instanceof TemporadaSerie) {
                        TemporadaSerie t = (TemporadaSerie) oArt;
                        if (t.estaPerdido(fecha)) {
                        deuda = deuda + Alquiler.PRECIO_SERIE;
                        } else {
                        articulos2.add(t);
                        }
                        } else if (o instanceof JuegoEducativo) {
                        JuegoEducativo je = (JuegoEducativo) oArt;
                        System.out.println("Codigo " + je.getCodigo());
                        if (je.estaPerdido(fecha)) {
                        deuda = deuda + Alquiler.PRECIO_JUEGO_EDUCATIVO;
                        } else {
                        articulos2.add(je);
                        }
                        } else if (o instanceof JuegoRecreativo) {
                        JuegoRecreativo jr = (JuegoRecreativo) oArt;
                        System.out.println("Codigo " + jr.getCodigo());
                        if (jr.estaPerdido(fecha)) {
                        deuda = deuda + Alquiler.PRECIO_JUEGO_RECREATIVO;
                        } else {
                        articulos2.add(jr);
                        }
                        }*/
                    }
                    //System.out.println("HOALaaaaa: "+articulos.size());
                    //alq.setArticulos(articulos);

                }
                System.out.println("op compra");
            }
            /*
            // Facturo la deuda del alquiler para ese asociado.
            if (deuda != 0.0) {
            System.out.println("HOLAAAA blas");
            if (o instanceof Asociado) {
            ((Asociado) o).setOperaciones(operaciones);
            fwEmp.append("f & " + ((Asociado) o).getCodigo() + " & " + deuda + "\n");
            generarFactura(
            ((Asociado) o), articulosPerdidos, "Perdida de Artículos", factura, deuda, inventario);
            } else {
            ((AsociadoPremium) o).setOperaciones(operaciones);
            fwEmp.append("f & " + ((AsociadoPremium) o).getCodigo() + " & " + deuda);
            generarFactura(
            ((AsociadoPremium) o), articulosPerdidos, "Perdida de Artículos", factura, deuda, inventario);
            }
            }*/
            deuda = 0.0;
        }
    }

    /**
     * Esta funcion verifica los alquileres y si hoy es el dia de devolución se llama
     * al asociad Premium para recordarle.
     * @param asociados Información de los asociados.
     * @param fwEmp FileWriter de las acciones de los empleados.
     * @param fecha fecha del dia con el que se va a comparar la fecha de vencimiento.
     * @exception IOException Si no se puede escribir en el archivo de acciones del empleado (fwEmp).
     */
    public static void recordarDevolucioAP(HashMap<String, Object> asociados, FileWriter fwEmp, GregorianCalendar fecha, HashMap<String, Object> inventario) throws Exception {
        ArrayList<Object> operaciones;
        ArrayList<Object> articulosDevolverHoy = null;
        Iterator it = asociados.entrySet().iterator();
        Iterator opIt;
        Object o;
        Alquiler alq;
        // iteramos sobre los asociados del hashmap.
        while (it.hasNext()) {
            Map.Entry e = (Map.Entry) it.next();
            //  SI es un asociado Premium se le recuerda si no no...
            if (e.getValue() instanceof AsociadoPremium) {
                // Obtenemos el asociado
                AsociadoPremium ap = (AsociadoPremium) e.getValue();
                // Para cada asociado obtenemos las operaciones
                operaciones = ap.getOperaciones();
                // Obtengo las operaciones que sean alquiler
                opIt = operaciones.iterator();

                // El asociado puede tener mas de un alquiler con
                // articulos por devolver hoy.
                while (opIt.hasNext()) {
                    o = opIt.next();
                    // si es un alquiler
                    if (o instanceof Alquiler) {
                        alq = (Alquiler) o;
                        articulosDevolverHoy = alq.getarticulosDevolverHoy(fecha);
                    }
                }

                // Si tengo algun articulo llamo al asociado Premium
                if (articulosDevolverHoy != null && !articulosDevolverHoy.isEmpty()) {
                    fwEmp.append("l & " + ap.getCodigo());
                }
            }
        }
    }

    //  ATENCION FALTA     @param fwFac FileWriter del archivo de las acciones realizadas por los empleados.
    /**
     * Este metodo se encarga de cargar las acciones que se reciben por un archivo String (archivo).
     * @param archivo Direccion del archivo a cargar.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     * @param asociados Informacion de los asociados a la tienda.
     * @param fwEmp FileWriter del archivo de las acciones realizadas por los empleados.
    
     * @exception Exception Si el formato de una linea del archivo es incorrecto.
     * @exception IOException Si no se puede escribir en el archivo de acciones del empleado (fwEmp).
     */
    public static void cargarAcciones(String archivo, HashMap<String, Object> inventario, HashMap<String, Object> asociados, FileWriter fwEmp, FileWriter fwFac) throws Exception {
        FileReader fr = new FileReader(archivo);
        BufferedReader br = new BufferedReader(fr);
        String linea = null;
        String acciones[];
        int numDias = 0;
        int numAcciones = 0;
        GregorianCalendar diaConsiderado = new GregorianCalendar();
        boolean terminoDia = false;
        HashMap<String, Cliente> clientes = new HashMap<String, Cliente>();

        if ((linea = br.readLine()) != null) {
            acciones = linea.split("\\s+");
            numDias = Integer.parseInt(acciones[0].trim());
            numAcciones = Integer.parseInt(acciones[1].trim());

        } else {
            throw new Exception("Formato primera linea incorrecto " + archivo);
        }

        if ((linea = br.readLine()) != null) {
            diaConsiderado = transformarFecha(linea, "dd/MM/yyyy");

        } else {
            throw new Exception("Formato segunda linea incorrecto " + archivo);
        }

        // Mientras  no haya llegado al final del archivo.
        while (((linea = br.readLine()) != null)) {

            // Para lineas del archivo que contienen algun caracter.
            if (!(linea.trim()).equals("")) {

                if (linea.equals("#") && (numDias != 0)) {
                    fwEmp.append("#\n");

                    //Al iniciar el dia liberamos los articulos que fueron llevados a caja
                    //y que no fueron pagos el dia anterior
                    liberarRecursos(asociados, clientes, inventario);

                    // se verifican las acciones a desarrollar al inicio de cada día.
                    chequearTcStatus(asociados, fwEmp, diaConsiderado);

                    ///ATENCION REVISAR
                    //        chequearPrestamosPerdidos(asociados, fwEmp, fwFac, diaConsiderado, inventario);
                    // Revisamos para los asociados premium sus prestamos
                    // y le recordamos su devolucion.
                    recordarDevolucioAP(asociados, fwEmp, diaConsiderado, inventario);
                    // Paso un Día
                    diaConsiderado.add(GregorianCalendar.DATE, 1);
                    numDias--;

                } else if (linea.equals("#") && (numDias == 0)) {
                    terminoDia = true;
                    fwEmp.append("#");

                } else if (!linea.equals("#") && !terminoDia) {

                    //Realizar acccionees
                    acciones = linea.split("\\s*&\\s*");

                    switch (acciones[0].toLowerCase().trim().charAt(0)) {

                        case 'a':
                            asociar(acciones, asociados, fwEmp, diaConsiderado);
                            break;

                        case 't':
                            actualizarTC(acciones, asociados, fwEmp, diaConsiderado);
                            break;

                        case 'c':
                            llevarACajaCompra(acciones, inventario, asociados, clientes, fwEmp);
                            break;

                        case 'r':
                            llevarACajaAlquiler(acciones, inventario, asociados, fwEmp, diaConsiderado);
                            break;

                        case 'p':
                            pagar(acciones, inventario, asociados, clientes, fwEmp, fwFac);
                            break;

                        case 'b':
                            System.out.println("");
                            abandonarTienda(acciones, inventario, asociados, clientes, fwEmp);
                            break;

                        case 'd':
                            //devolverArticulo(acciones, inventario, asociados, fwEmp, fwFac, diaConsiderado);
                            break;

                        case 'e':
                            recogerArticulo(acciones, inventario, asociados, fwEmp, fwFac, diaConsiderado);
                            break;

                        default:
                            System.out.println("Operacion no valida");
                            break;
                    }
                    numAcciones--;

                } else if (terminoDia) {
                    throw new Exception("Archivo " + archivo + "Invalido: numero de dias mayor al especificado.");
                }
            }
        }

        if (numDias != 0) {
            throw new Exception("Archivo " + archivo + "Invalido: numero de dias menor al especificado en la primera linea.");
        }

        if (!terminoDia) {
            throw new Exception("Archivo " + archivo + "Invalido: formato de dias no valido.");
        }

        if (numAcciones != 0) {
            throw new Exception("Archivo " + archivo + "Invalido: numero de acciones distinto al especificado en la primera linea.");
        }
    }

    /**
     * Este metodo se encarga de Imprimir el inventario que queda luego de n días.
     * @param FArticulos FileWriter del archivo de salida de los artículos.
     * @param inv Inventario de los artículos.
     * @exception IOException Si no se puede escribir en el archivo de Salida.
     */
    public static void imprimirInventario(FileWriter FArticulos, HashMap<String, Object> inv) throws Exception {

        Iterator it = inv.entrySet().iterator();
        FArticulos.append(inv.entrySet().size() + "\n");

        // iteramos sobre los asociados del hashmap.
        while (it.hasNext()) {
            Map.Entry e = (Map.Entry) it.next();
            FArticulos.append(e.getKey() + " & ");

            if (e.getValue() instanceof Pelicula) {
                Pelicula p = (Pelicula) e.getValue();
                FArticulos.append(p.obtenerDatos());

            } else if (e.getValue() instanceof TemporadaSerie) {
                TemporadaSerie t = (TemporadaSerie) e.getValue();
                FArticulos.append(t.obtenerDatos());

            } else if (e.getValue() instanceof JuegoEducativo) {
                JuegoEducativo JE = (JuegoEducativo) e.getValue();
                FArticulos.append(JE.obtenerDatos());

            } else if (e.getValue() instanceof JuegoRecreativo) {
                JuegoRecreativo JR = (JuegoRecreativo) e.getValue();
                FArticulos.append(JR.obtenerDatos());

            }
            FArticulos.append("\n");
        }
    }

    /**
     * Este metodo se encarga de Imprimir los asociados que quedan junto con su informacion luego de n días.
     * @param FAsociados FileWriter del archivo de salida de los Asociados.
     * @param asociados Inventario de los asociados.
     * @exception IOException Si no se puede escribir en el archivo de Salida.
     */
    public static void imprimirAsociados(FileWriter FAsociados, HashMap<String, Object> asociados) throws Exception {

        Iterator it = asociados.entrySet().iterator();
        FAsociados.append(asociados.entrySet().size() + " " + codigoAsociado + "\n");

        // iteramos sobre los asociados del hashmap.
        while (it.hasNext()) {
            Map.Entry e = (Map.Entry) it.next();
            Object o = e.getValue();

            if (o instanceof Asociado) {
                Asociado a = (Asociado) o;
                FAsociados.append(a.obtenerDatosAsociado() + "\n");

            } else {
                AsociadoPremium a = (AsociadoPremium) o;
                FAsociados.append(a.obtenerDatosAsociado() + "\n");
            }
        }
    }

    // ATENCION CHEQUAR POR QUE LA SALIDA NO CUMPLE CON EL FORMATO
    /**
     * Este metodo se encarga de Imprimir los prestamos luego de las accines realizadas por los clientes.
     * @param FPrestamos FileWriter del archivo de salida de los Prestamos.
     * @param asociados Inventario de los asociados.
     * @exception IOException Si no se puede escribir en el archivo de Salida.
     */
    public static void imprimirPrestamos(FileWriter FPrestamos, HashMap<String, Object> asociados) throws Exception {

        Iterator it = asociados.entrySet().iterator();
        Object oAsoc;
        // Para cada asociado
        while (it.hasNext()) {

            Map.Entry e = (Map.Entry) it.next();
            oAsoc = e.getValue();
            // Obtenemos al asociado
            if (oAsoc instanceof AsociadoPremium) {
                AsociadoPremium ap = (AsociadoPremium) oAsoc;
                FPrestamos.append(ap.obtenerPrestamos());

            } else if (oAsoc instanceof Asociado) {
                Asociado asoc = (Asociado) oAsoc;
                FPrestamos.append(asoc.obtenerPrestamos());
            }
        }
    }

    // ATENCION QUITAR
    /*
     * Este metodo se encarga de Imprimir las facturas luego de cada compra, alquiler o perdida.
     * @param fw FileWriter del archivo de salida de las facturas.
     * @exception IOException Si no se puede escribir en el archivo de Salida.
     */
    /*
    public static void imrpimirFactura(FileWriter fw) throws Exception {
    }*/
    /**
     * Este metodo se encarga de validar que una ruta dada sea de un archivo.
     * @param dir Direccion del archivo
     */
    public static boolean existeArchivo(String dir) {
        File f = new File(dir);
        return (f.exists() && f.isFile());

    }

    /**
     * Este metodo Valida que una ruta dada sea un archivo.
     * @param arch Ruta del archivo.
     * @exception Exception Retorna una excepción cuando el archivo no existe.
     */
    public static void validarArchivo(String arch) throws Exception {
        File f = new File(arch);

        if (!f.exists() || !f.isFile()) {
            throw new Exception("El directorio no es Correcto o el Archivo "
                    + arch + "no Existe.");
        }
    }

    /**
     * Este metodo verifica que al finalizar el dia, si una persona lleva articulos a caja pero no los paga
     * se libera ese articulo para el inventario.
     * @param asociados  consiste en un HashMap que contiene informacion de todos los Asociados registrados.
     * @param clientes   consiste en un HashMap que contiene informacion de todos los Clientes registrados.
     * @param inventario consiste en un HashMap que contiene informacion de todos los articulos registrados.
     */
    public static void liberarRecursos(HashMap<String, Object> asociados, HashMap<String, Cliente> clientes, HashMap<String, Object> inventario) {
        //Por cada asociado itero sobre su lista de operaciones para eliminar
        //articulos que haya llevado a caja y que no pago

        int i = 0;
        int k = 0;
        String codArticulo;

        Iterator it = asociados.entrySet().iterator();

        // Para cada asociado, eliminamos sus articulos llevados a caja
        while (it.hasNext()) {

            Map.Entry e = (Map.Entry) it.next();
            Asociado asoc = (Asociado) e.getValue();

            //Verificamos si posee articulos para alquilar o comprar para luego poder liberarlos
            ArrayList<Object> artCompra = asoc.obtenerArticulosCompra();
            ArrayList<Object> artAlquiler = asoc.obtenerArticulosAlquiler();

            //Iteramos por la lista de compras y sumamos 1 a la cantidad de ese art. en inventario
            while (k < artCompra.size()) {
                Articulo art = (Articulo) artCompra.get(k);
                codArticulo = art.getCodigo();
                Articulo artInv = (Articulo) inventario.get(codArticulo);
                artInv.setCantidad(artInv.getCantidad() + 1);
                k++;
            }

            k = 0;

            //Iteramos por la lista de alquileres y sumamos 1 a la cantidad de ese art. en inventario
            while (k < artAlquiler.size()) {

                Articulo art = (Articulo) artAlquiler.get(k);
                codArticulo = art.getCodigo();
                Articulo artInv = (Articulo) inventario.get(codArticulo);
                artInv.setCantidad(artInv.getCantidad() + 1);
                k++;
            }

            asoc.eliminarArticulosAlquiler();
            asoc.eliminarArticulosCompra();

        }

        it = clientes.entrySet().iterator();

        //Para cada cliente, eliminamos sus articulos llevados a caja
        while (it.hasNext()) {

            Map.Entry e = (Map.Entry) it.next();
            Cliente client = (Cliente) e.getValue();

            ArrayList<Object> artComp = client.obtenerArticulosCompra();
            k = 0;

            //Iteramos por la lista de compras y sumamos 1 a la cantidad de ese art. en inventario
            while (k < artComp.size()) {

                Articulo art = (Articulo) artComp.get(k);
                codArticulo = art.getCodigo();
                Articulo artInv = (Articulo) inventario.get(codArticulo);
                artInv.setCantidad(artInv.getCantidad() + 1);
                k++;
            }

            client.eliminarArticulosCompra();

        }


    }

    /**
     * Este es el metodo principal de ejecucion del archivo.
     * @param args Argumentos de entrada.
     * @exception Exception Retorna una excepción generada por alguna de las
     * funciones que se invocan.
     */
    public static void main(String args[]) {
        HashMap<String, Object> asociados = new HashMap<String, Object>();
        HashMap<String, Object> inventario = new HashMap<String, Object>();
        FileWriter fwe, fwf, fw3, fw4, fw5;

        if (args.length != 8) {
            System.out.println("Numero incorrecto de argumentos en la llamada del programa.\n"
                    + "Uso: java VideoRent <a> <b> <c> <d> <e> <f> <g> <h>\n"
                    + "Donde: \n"
                    + "\t a es la direccion del archivo de entrada que contiene "
                    + "la informacion de los artículos en existencia.\n"
                    + "\t b es la direccion del archivo de entrada que contiene "
                    + "la informacion de los clientes previamente asociados.\n"
                    + "\t c es la direccion del archivo de entrada que contiene "
                    + "la informacion de las acciones realizadas por los "
                    + "clientes en un plazo de n días.\n"
                    + "\t d es la dirección junto con el nombre donde se va a "
                    + "imprimir las acciones realizadas por los empleados de la tienda en un plazo de n días.\n"
                    + "\t e es la dirección junto con el nombre donde se va a "
                    + "imprimir ls informacion de las facturas generadas en un plazo de n días.\n"
                    + "\t f es la dirección junto con el nombre donde se va a "
                    + "imprimir la información de los artículos en existencia luego de n días.\n"
                    + "\t g es la dirección junto con el nombre donde se va a "
                    + "imprimir la informacion de los asociados luego de las acciones realizadas en un plazo de n días.\n"
                    + "\t h es la dirección junto con el nombre donde se va a "
                    + "imprimir la informacion de los artículos en prestamo luego de un plazo de n días.\n"
                    + "Ejemplo:\n"
                    + "\t java VideoRent \"./articulosExistentesAntes\" \"./clientesAsociadosAntes\""
                    + " \"./accionesClientes\" \"./accionesEmpleados\" \"./FacturasGeneradas\""
                    + " \"./articulosExistentesDespues\" \"./clientesAsociadosDespues\" \"./prestamos\"");
            System.exit(0);
        }
        try {
            for (int i = 0; i
                    < 3; i++) {
                //Verificamos que la ruta dada sea de un archivo
                validarArchivo(args[i]);
            }
            for (int i = 3; i
                    < args.length; i++) {

                if (existeArchivo(args[i])) {
                throw new Exception("Nombre De archivo para escritura " + args[i] + " ya existe, elija otro.");
                }
            }

            // Cargar los artículos existentes.

            inventario = cargarArticulos(args[0]);
            // Cargar los Asociados.
            asociados = cargarAsociados(args[1]);
            // Realizar una a una las acciones del cliente.

            // Creamos Archivo de acciones empleados
            fwe = new FileWriter(args[3]);
            // Creamos Archivo de facturas generadas
            fwf = new FileWriter(args[4]);
            // Imprimir las acciones de los empleados.
            cargarAcciones(args[2], inventario, asociados, fwe, fwf);

            // Imprimir el inventario.
            fw3 = new FileWriter(args[5]);
            imprimirInventario(fw3, inventario);

            // Imprimir los clientes Asociados.
            fw4 = new FileWriter(args[6]);
            imprimirAsociados(fw4, asociados);

            // Imprimir los Prestamos.
            fw5 = new FileWriter(args[7]);
            imprimirPrestamos(fw5, asociados);

            fwe.close();
            fwf.close();
            fw3.close();
            fw4.close();
            fw5.close();


        } catch (Exception E) {
            System.out.println("Ha ocurrido un error con uno o más archivos de "
                    + "entrada:\n" + E);
            System.exit(0);
        }
    }
}
